//
//  ViewController.m
//  KeyboardMonitor
//
//  Created by flynn on 2025/6/16.
//

#import "ViewController.h"
#import <Carbon/Carbon.h>
@interface ViewController()
@property (weak) IBOutlet NSScrollView *txtKeyResult;
@property (nonatomic,assign)id globalmonitor;
@property (nonatomic,assign)id localmonitor;
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}
-(NSString* )getKeyNameWithKeyCode:(int)iKeyCode
{
    NSDictionary *dicKeyCode = @{
        @"a":[NSNumber numberWithInt:kVK_ANSI_A],
        @"s":[NSNumber numberWithInt:kVK_ANSI_S],
        @"d":[NSNumber numberWithInt:kVK_ANSI_D],
        @"f":[NSNumber numberWithInt:kVK_ANSI_F],
        @"h":[NSNumber numberWithInt:kVK_ANSI_H],
        @"g":[NSNumber numberWithInt:kVK_ANSI_G],
        @"z":[NSNumber numberWithInt:kVK_ANSI_Z],
        @"x":[NSNumber numberWithInt:kVK_ANSI_X],
        @"c":[NSNumber numberWithInt:kVK_ANSI_C],
        @"v":[NSNumber numberWithInt:kVK_ANSI_V],
        @"b":[NSNumber numberWithInt:kVK_ANSI_B],
        @"q":[NSNumber numberWithInt:kVK_ANSI_Q],
        @"w":[NSNumber numberWithInt:kVK_ANSI_W],
        @"e":[NSNumber numberWithInt:kVK_ANSI_E],
        @"r":[NSNumber numberWithInt:kVK_ANSI_R],
        @"y":[NSNumber numberWithInt:kVK_ANSI_Y],
        @"t":[NSNumber numberWithInt:kVK_ANSI_T],
        @"o":[NSNumber numberWithInt:kVK_ANSI_O],
        @"u":[NSNumber numberWithInt:kVK_ANSI_U],
        @"i":[NSNumber numberWithInt:kVK_ANSI_I],
        @"p":[NSNumber numberWithInt:kVK_ANSI_P],
        @"l":[NSNumber numberWithInt:kVK_ANSI_L],
        @"j":[NSNumber numberWithInt:kVK_ANSI_J],
        @"k":[NSNumber numberWithInt:kVK_ANSI_K],
        @"m":[NSNumber numberWithInt:kVK_ANSI_M],
        @"n":[NSNumber numberWithInt:kVK_ANSI_N],
        @"1":[NSNumber numberWithInt:kVK_ANSI_1],
        @"2":[NSNumber numberWithInt:kVK_ANSI_2],
        @"3":[NSNumber numberWithInt:kVK_ANSI_3],
        @"4":[NSNumber numberWithInt:kVK_ANSI_4],
        @"5":[NSNumber numberWithInt:kVK_ANSI_5],
        @"6":[NSNumber numberWithInt:kVK_ANSI_6],
        @"7":[NSNumber numberWithInt:kVK_ANSI_7],
        @"8":[NSNumber numberWithInt:kVK_ANSI_8],
        @"9":[NSNumber numberWithInt:kVK_ANSI_9],
        @"0":[NSNumber numberWithInt:kVK_ANSI_0],
        @"f1":[NSNumber numberWithInt:kVK_F1],
        @"f2":[NSNumber numberWithInt:kVK_F2],
        @"f3":[NSNumber numberWithInt:kVK_F3],
        @"f4":[NSNumber numberWithInt:kVK_F4],
        @"f5":[NSNumber numberWithInt:kVK_F5],
        @"f6":[NSNumber numberWithInt:kVK_F6],
        @"f7":[NSNumber numberWithInt:kVK_F7],
        @"f8":[NSNumber numberWithInt:kVK_F8],
        @"f9":[NSNumber numberWithInt:kVK_F9],
        @"f10":[NSNumber numberWithInt:kVK_F10],
        @"f11":[NSNumber numberWithInt:kVK_F11],
        @"f12":[NSNumber numberWithInt:kVK_F12],
        @"f13":[NSNumber numberWithInt:kVK_F13],
        @"f14":[NSNumber numberWithInt:kVK_F14],
        @"f15":[NSNumber numberWithInt:kVK_F15],
        @"f16":[NSNumber numberWithInt:kVK_F16],
        @"f17":[NSNumber numberWithInt:kVK_F17],
        @"f18":[NSNumber numberWithInt:kVK_F18],
        @"f19":[NSNumber numberWithInt:kVK_F19],
        @"f20":[NSNumber numberWithInt:kVK_F20],
        @"Numpad0":[NSNumber numberWithInt:kVK_ANSI_Keypad0],
        @"Numpad1":[NSNumber numberWithInt:kVK_ANSI_Keypad1],
        @"Numpad2":[NSNumber numberWithInt:kVK_ANSI_Keypad2],
        @"Numpad3":[NSNumber numberWithInt:kVK_ANSI_Keypad3],
        @"Numpad4":[NSNumber numberWithInt:kVK_ANSI_Keypad4],
        @"Numpad5":[NSNumber numberWithInt:kVK_ANSI_Keypad5],
        @"Numpad6":[NSNumber numberWithInt:kVK_ANSI_Keypad6],
        @"Numpad7":[NSNumber numberWithInt:kVK_ANSI_Keypad7],
        @"Numpad8":[NSNumber numberWithInt:kVK_ANSI_Keypad8],
        @"Numpad9":[NSNumber numberWithInt:kVK_ANSI_Keypad9],
        @"Backspace":[NSNumber numberWithInt:kVK_Space],
    };

    for (NSString* key in dicKeyCode.allKeys) {
        if ([[dicKeyCode objectForKey:key] intValue] == iKeyCode)
            return key;
    }
    return @"";
}
- (IBAction)onStartMonitor:(id)sender {
    if (AXIsProcessTrusted())
    {
        // 当前App处于非激活前台时才能接收到KeyDown事件，如果处于激活前台，则无法接收到KeyDown事件
        self.globalmonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^(NSEvent *event) {
            NSMutableString* strResult = [NSMutableString string];
            if ([event modifierFlags] & NSEventModifierFlagOption) [strResult appendString:@"alt/option " ];
            if ([event modifierFlags] & NSEventModifierFlagCommand) [strResult appendString:@"command " ];
            if ([event modifierFlags] & NSEventModifierFlagShift) [strResult appendString:@"shift " ];
            if ([event modifierFlags] & NSEventModifierFlagCapsLock) [strResult appendString:@"capslock " ];
            if ([event modifierFlags] & NSEventModifierFlagControl) [strResult appendString:@"ctrl " ];
            int ikeycode = event.keyCode;
            NSString* strKey = [self getKeyNameWithKeyCode:ikeycode];
            [strResult appendString:strKey];
            NSTextView* txt =  self.txtKeyResult.documentView;
            txt.string = [txt.string stringByAppendingFormat:@"\n%@",strResult];
        }];
        // 当前App处于激活前台时，接收的keydown事件只能通过local监控的方式来实现
        self.localmonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
            NSMutableString* strResult = [NSMutableString string];
            if ([event modifierFlags] & NSEventModifierFlagOption) [strResult appendString:@"alt/option " ];
            if ([event modifierFlags] & NSEventModifierFlagCommand) [strResult appendString:@"command " ];
            if ([event modifierFlags] & NSEventModifierFlagShift) [strResult appendString:@"shift " ];
            if ([event modifierFlags] & NSEventModifierFlagCapsLock) [strResult appendString:@"capslock " ];
            if ([event modifierFlags] & NSEventModifierFlagControl) [strResult appendString:@"ctrl " ];
            int ikeycode = event.keyCode;
            NSString* strKey = [self getKeyNameWithKeyCode:ikeycode];
            [strResult appendString:strKey];
            NSTextView* txt =  self.txtKeyResult.documentView;
            txt.string = [txt.string stringByAppendingFormat:@"\n%@",strResult];
            return event;
        }];
        return ;
    }
    else
    {
        CFStringRef keys[] = {kAXTrustedCheckOptionPrompt};
        CFBooleanRef values[] = {kCFBooleanTrue};
        //keyCallBacks：字典键值的回调，系统预设值kCFTypeDictionaryKeyCallBacks适用于所有CFTypes类型；当KEY是可变类型时，需要保存一个不可变的副本，需要使用kCFCopyStringDictionaryKeyCallBacks；
        //valueCallBacks:系统预设值kCFTypeDictionaryValueCallBacks适用于所有CFTypes类型
        CFDictionaryRef dic = CFDictionaryCreate(CFAllocatorGetDefault(), (const void**)keys, (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        Boolean ret = AXIsProcessTrustedWithOptions(dic);
    }
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}


@end
